import 'dart:async';

import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/material.dart';
import 'package:geolocation/models/position.dart';
import 'package:get/get.dart';

import '../../../../common/api/index.dart';
import '../../../../common/models/index.dart';
import '../../../../common/routers/index.dart';
import '../../../../common/services/index.dart';
import '../../../../common/utils/index.dart';
import '../../../../common/extension/index.dart';
import '../../../../common/widgets/index.dart';
import '../attendance_setting/view.dart';
import 'index.dart';

class MainController extends GetxController with WidgetsBindingObserver {
  MainController();

  final state = MainState();

  final pageViewController = PageController();

  // 外勤打卡，需要输入说明
  final TextEditingController outsideCheckInDescInputController =
      TextEditingController();
  // 设备信息插件
  final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();

  // 定时器
  Timer? _timer;

  /// geolocator 定位
  GeolocatorHelper? _geoHelper;

  /// 当前定位信息
  GeoPosition? myPosition;

  // 工作地点
  List<WorkPlaceList> workplaceList = [];
  WorkPlaceList? nearLeastWorkplace; // 范围内的打卡地点
  // BaiduLocation? myLocation; // 当前定位信息
  AttendanceV2Record? currentCheckItem; // 当前打卡对象
  bool allowFieldWork = false; // 是否允许外勤打卡
  bool requiredFieldWorkRemarks = false; // 描述是否必填
  // 配置文件
  AttendanceV2Config? config;

  /// 在 widget 内存中分配后立即调用。
  @override
  void onInit() {
    WidgetsBinding.instance.addObserver(this);
    super.onInit();
  }

  /// 在 onInit() 之后调用 1 帧。这是进入的理想场所
  @override
  void onReady() {
    loadConfig();
    state.title = Get.parameters['displayName'] ?? "app_name_attendance".tr;

    /// 间隔1秒
    _timer = Timer.periodic(const Duration(milliseconds: 1000), (timer) {
      ///定时任务
      _updateTimePerSecond();
    });
    // 初始化定位程序
    _geoHelper = GeolocatorHelper(callback: (position) {
      myPosition = position;
      _calNearestWorkplace();
    });
    _geoHelper?.startLocation();
    // 初始化数据
    _loadPreCheckInData();
    _loadMyStatisticData();
    super.onReady();
  }

  /// 在 [onDelete] 方法之前调用。
  @override
  void onClose() {
    // 取消定时器
    _timer?.cancel();
    _geoHelper?.stopLocation();
    WidgetsBinding.instance.removeObserver(this);
    super.onClose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) async {
    OLogger.d("attendance LifecycleState ==========  $state");
    if (state == AppLifecycleState.resumed) {
      OLogger.d('重新进入 刷新数据！');
      _loadPreCheckInData();
    }
  }

  gotoSetting() {
    AttendanceSettingPage.open();
  }

  /// 进入异常数据页面
  void clickOpenExceptionPage() {
    OLogger.d('点击了 异常数据页面');
    Get.toNamed(O2OARoutes.appAttendanceExceptionDataPage);
  }

  /// pageView
  void handlePageChanged(int page) {
    OLogger.d("切换pageView page:$page");
  }

  /// 底部栏
  void handleNavBarTap(int page) {
    state.currentIndex = page;
    pageViewController.jumpToPage(page);
  }

  /// 更新打卡记录
  void clickUpdateRecord(BuildContext context, AttendanceV2Record info) {
    if (info.isLastRecord) {
      OLogger.d('更新打卡，${info.checkInType}');
      O2UI.showConfirm(context, 'attendance_update_confirm_content'.tr,
          okPressed: () {
        _checkinClickOrUpdate(context,
            recordId: info.id, recordType: info.checkInType);
      });
    }
  }

  /// 打卡
  void clickCheckIn(BuildContext context) {
    OLogger.d('点击打卡');
    if (!state.todayNeedCheck) {
      OLogger.e('今日不需要打卡了，已经完成！');
      return;
    }
    _checkinClickOrUpdate(context);
  }

  /// 初始化底部导航栏
  void initBottomBar() {
    // 查询是否管理员 更新底部导航栏
    state.bottomTabs = <BottomNavigationBarItem>[
      BottomNavigationBarItem(
          icon: const Icon(Icons.location_on),
          activeIcon: const Icon(Icons.location_on),
          label: 'attendance_tab_checkin'.tr),
      BottomNavigationBarItem(
          icon: const Icon(Icons.pie_chart),
          activeIcon: const Icon(Icons.pie_chart),
          label: 'attendance_tab_statistic'.tr),
    ];
  }

  /// 加载配置
  Future<void> loadConfig() async {
    final result = await AttendanceAssembleControlService.to.config();
    config = result;
  }

  /// 统计
  _loadMyStatisticData() async {
    final now = DateTime.now();
    final startDate = now.monthFirstDate();
    final endDate = now.monthLastDate();
    state.currentYear = '${now.year}';
    state.currentMonth = 'attendance_statistic_month'.trArgs(['${now.month}']);
    final result = await AttendanceAssembleControlService.to
        .myStatistic(startDate.ymd(), endDate.ymd());
    if (result != null) {
      state.myStatistic.value = result;
    }
  }

  ///
  /// 获取打卡初始化数据
  ///
  void _loadPreCheckInData() async {
    var data = await AttendanceAssembleControlService.to.loadPreCheckInData();
    if (data != null) {
      bool needCheck = data.canCheckIn ?? false; //今天是否还需要打卡
      allowFieldWork = data.allowFieldWork ?? false;
      requiredFieldWorkRemarks = data.requiredFieldWorkRemarks ?? false;
      // 打卡记录
      var checkItemList = data.checkItemList ?? [];
      // 是否最后一条已经打卡过的数据
      currentCheckItem = checkItemList
          .firstWhereOrNull((element) => element.checkInResult == 'PreCheckIn');
      if (currentCheckItem != null) {
        needCheck = true;
      } else {
        needCheck = false;
      }
      for (var i = 0; i < checkItemList.length; i++) {
        var item = checkItemList[i];
        if (item.checkInResult != 'PreCheckIn') {
          if (i == checkItemList.length - 1) {
            item.isLastRecord = true;
            checkItemList[i] = item;
          } else {
            var nextItem = checkItemList[i + 1];
            if (nextItem.checkInResult == 'PreCheckIn') {
              item.isLastRecord = true;
              checkItemList[i] = item;
            }
          }
        }
      }
      state.todayNeedCheck = needCheck;
      state.checkItemList.clear();
      state.checkItemList.addAll(checkItemList);

      // 工作场所
      _listAllAttendanceWorkPlace(data.workPlaceList);
    } else {
      Loading.showError('attendance_request_error'.tr);
      Get.back();
    }
  }

  void _listAllAttendanceWorkPlace(List<WorkPlaceList>? list) {
    if (list != null && list.isNotEmpty) {
      workplaceList.clear();
      workplaceList.addAll(list);
      // 计算最近的打卡地点
      _calNearestWorkplace();
    }
  }

  ///
  /// 提交打卡
  ///
  void _postCheckIn(
      String latitude, String longitude, String addrStr, String checkType,
      {String workPlaceId = '',
      String signDesc = '',
      String id = '',
      bool isExternal = false,
      String workAddress = ''}) async {
    final result = await FastCheckInService.instance.checkinPost(
        latitude, longitude, addrStr, checkType, 'USER_CHECK',
        workAddress: workAddress,
        workPlaceId: workPlaceId,
        signDesc: signDesc,
        isExternal: isExternal,
        id: id,
        showLoading: true);
    if (result) {
      _loadPreCheckInData();
    }

    // if (isExternal) {
    //   // 外勤打开
    //   if (signDesc.isEmpty) {
    //     Loading.toast('attendance_outside_need_desc'.tr);
    //     return;
    //   }
    // }
    // final check = await faceDetection();
    // if (!check) {
    //   OLogger.e('message: 人脸识别失败！');
    //   return;
    // }
    // Loading.show();
    // var post = CheckPost(
    //     recordId: id,
    //     checkInType: checkType,
    //     workPlaceId: workPlaceId,
    //     fieldWork: isExternal,
    //     signDescription: signDesc,
    //     latitude: latitude,
    //     longitude: longitude,
    //     recordAddress: addrStr,
    //     sourceType: 'USER_CHECK');
    // var deviceType = SharedPreferenceService.to
    //     .getString(SharedPreferenceService.currentDeviceTypeKey);

    // final checkScript =
    //     await _externalCheck(id, deviceType, checkType, isExternal);
    // if (!checkScript.check) {
    //   Loading.dismiss();
    //   OLogger.e('打卡检查脚本失败, ${checkScript.deviceId} ${checkScript.message}');
    //   var message = 'attendance_checkin_external_check_error'.tr;
    //   if (checkScript.message != null && checkScript.message!.isNotEmpty) {
    //     message = checkScript.message!;
    //   }
    //   Loading.toast(message);
    //   return;
    // }
    // post.sourceDevice = checkScript.deviceId;

    // var iddata = await AttendanceAssembleControlService.to.checkInPostV2(post);
    // if (iddata != null) {
    //   Loading.dismiss();
    //   _loadPreCheckInData();
    // }
  }
   
  ///
  /// 查找最近的打卡地点
  ///
  void _calNearestWorkplace() async {
    if (myPosition == null) {
      OLogger.e('还没有定位成功！');
      return;
    }
    state.currentAddress = 'attendance_checkin_not_in_workplace_error'.tr;
    state.isInCheckInPositionRange = false;
    if (workplaceList.isNotEmpty) {
      for (var workplace in workplaceList) {
        OLogger.d('工作地点： ${workplace.latitude}  ${workplace.longitude}');
        double startLatitude = myPosition?.latitude ?? 0;
        double startLongitude = myPosition?.longitude ?? 0;
        final lngLat = workplace.getLngLat();
        double endLatitude = lngLat[1];
        double endLongitude = lngLat[0];
        if (startLatitude != 0 &&
            startLongitude != 0 &&
            endLatitude != 0 &&
            endLongitude != 0) {
          OLogger.d(
              '坐标  workplace endLatitude:$endLatitude endLongitude:$endLongitude myPosition startLatitude: $startLatitude startLongitude: $startLongitude');
          final distance = _geoHelper?.distanceInMeters(
                  startLatitude, startLongitude, endLatitude, endLongitude) ??
              0;
          int range = workplace.errorRange ?? 100; // 默认 100 米
          OLogger.d('距离计算：$distance $range');
          if (distance != 0 && distance <= range) {
            state.currentAddress = workplace.placeName;
            state.isInCheckInPositionRange = true;
            nearLeastWorkplace = workplace;
            break;
          }
        } else {
          OLogger.e(
              ' 错误的坐标  workplace endLatitude:$endLatitude endLongitude:$endLongitude myPosition startLatitude: $startLatitude startLongitude: $startLongitude');
        }
      }
      OLogger.d('找到最近的打卡点? ${nearLeastWorkplace?.placeName ?? '无'}');
    }
  }

  /// 每秒更新一次时间
  void _updateTimePerSecond() {
    var time = DateTime.now();
    state.currentTime = time.hms();
  }

  /// 打卡处理
  ///
  /// @param recordId 更新打卡的id
  /// @param recordType 更新打卡的类型
  void _checkinClickOrUpdate(BuildContext context,
      {String? recordId, String? recordType}) {
    if (myPosition == null) {
      Loading.toast('attendance_checkin_need_location'.tr);
      return;
    }
    if (state.isInCheckInPositionRange && nearLeastWorkplace != null) {
      // 正常打卡
      OLogger.i('正常打卡！');
      // 计算checkin type
      try {
        String checkType = recordType ?? '';
        String id = recordId ?? '';
        if (checkType.isEmpty || id.isEmpty) {
          checkType = currentCheckItem?.checkInType ?? '';
          id = currentCheckItem?.id ?? '';
          // 检查打卡 限制时间
          var preDutyTimeBeforeLimit =
              currentCheckItem?.preDutyTimeBeforeLimit ?? '';
          var preDutyTimeAfterLimit =
              currentCheckItem?.preDutyTimeAfterLimit ?? '';
          if (!_checkLimitTime(preDutyTimeBeforeLimit, preDutyTimeAfterLimit)) {
            return;
          }
        }
        // '${myLocation!.address}'
        _postCheckIn('${myPosition!.latitude}', '${myPosition!.longitude}',
            myPosition!.address ?? '', checkType,
            workPlaceId: nearLeastWorkplace!.id ?? '',
            workAddress: nearLeastWorkplace!.placeName ?? '',
            id: id);
      } catch (e) {
        OLogger.e(e);
        Loading.toast('attendance_checkin_type_empty'.tr);
      }
    } else {
      // 外勤打开
      OLogger.i('外勤打卡');
      _outsideCheckIn(context, recordId: recordId, recordType: recordType);
    }
  }

  /// 是否有打卡时间限制
  bool _checkLimitTime(
      String preDutyTimeBeforeLimit, String preDutyTimeAfterLimit) {
    if (preDutyTimeBeforeLimit.isNotEmpty) {
      var now = DateTime.now();
      var today = now.ymd();
      var beforeTime = DateTime.tryParse("$today $preDutyTimeBeforeLimit:00");
      if (beforeTime != null && now.isBefore(beforeTime)) {
        Loading.toast('attendance_checkin_limit_time_error'
            .trArgs([preDutyTimeBeforeLimit, preDutyTimeAfterLimit]));
        return false;
      }
    }
    if (preDutyTimeAfterLimit.isNotEmpty) {
      var now = DateTime.now();
      var today = now.ymd();
      var afterTime = DateTime.tryParse("$today $preDutyTimeAfterLimit:00");
      if (afterTime != null && now.isAfter(afterTime)) {
        Loading.toast('attendance_checkin_limit_time_error'
            .trArgs([preDutyTimeBeforeLimit, preDutyTimeAfterLimit]));
        return false;
      }
    }
    return true;
  }

  /// 外勤打卡
  void _outsideCheckIn(BuildContext context,
      {String? recordId, String? recordType}) async {
    if (!allowFieldWork) {
      Loading.toast('attendance_checkin_outside_not_allow'.tr);
      return;
    }
    // 确认外勤打卡 dialog
    var result = await O2UI.showCustomDialog(
        context,
        'attendance_checkin_outside_dialog_title'.tr,
        TextField(
          controller: outsideCheckInDescInputController,
          maxLines: 1,
          style: Theme.of(context).textTheme.bodyMedium,
          keyboardType: TextInputType.text,
          textInputAction: TextInputAction.done,
          decoration: InputDecoration(
            hintText: 'attendance_checkin_outside_dialog_hint'.tr,
          ),
        ));
    OLogger.d('外勤打卡，返回结果$result');
    if (result != null && result == O2DialogAction.positive) {
      var desc = outsideCheckInDescInputController.text;
      if (desc.isEmpty && requiredFieldWorkRemarks) {
        Loading.toast('attendance_checkin_outside_dialog_hint'.tr);
      } else {
        // 计算checkin type
        try {
          String checkType = recordType ?? '';
          String id = recordId ?? '';
          if (checkType.isEmpty || id.isEmpty) {
            checkType = currentCheckItem?.checkInType ?? '';
            id = currentCheckItem?.id ?? '';
            // 检查打卡 限制时间
            var preDutyTimeBeforeLimit =
                currentCheckItem?.preDutyTimeBeforeLimit ?? '';
            var preDutyTimeAfterLimit =
                currentCheckItem?.preDutyTimeAfterLimit ?? '';
            if (!_checkLimitTime(
                preDutyTimeBeforeLimit, preDutyTimeAfterLimit)) {
              return;
            }
          }
          _postCheckIn('${myPosition!.latitude}', '${myPosition!.longitude}',
              myPosition!.address ?? '', checkType,
              signDesc: desc, isExternal: true, id: id);
        } catch (e) {
          OLogger.e(e);
          Loading.toast('attendance_checkin_type_empty'.tr);
        }
      }
    }
  }
}
